﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;
using System.ComponentModel;

namespace My.Common.Helper.JqGrid
{
    public class SortBuilder : ISortBuilder
    {
        private IConversionHelper _conversionHelper;
        private IModelHelper _modelHelper;

        public SortBuilder(IConversionHelper conversionHelper, IModelHelper modelHelper)
        {
            _conversionHelper = conversionHelper;
            _modelHelper = modelHelper;
        }

        public List<T> Sort<T>(List<T> source, string sortName, string sortOrder)
        {
            if (source != null && source.Any() && sortName != string.Empty
                && sortOrder != string.Empty)
            {
                var propertyName = _modelHelper.GetPropertyNameOfEntityByDisplayName<T>(sortName);
                if (propertyName != string.Empty)
                {
                    Comparison<T> comparisonDelegate = CreateComparison<T>(propertyName, sortOrder);

                    source.Sort(comparisonDelegate);
                }
            }

            return source;
        }

        private Comparison<T> CreateComparison<T>(string propertyName, string sortOrder)
        {
            int sortReverser = sortOrder.ToLower().StartsWith("asc") ? 1 : -1;

            return new Comparison<T>(delegate(T x, T y)
            {
                Type propertyType = _modelHelper.GetPropertyType(x.GetType(), propertyName);
                MethodInfo compareToMethod = GetCompareToMethod(propertyType);

                object xSortExpressionValue = x.GetType().GetProperty(propertyName).GetValue(x, null);
                if (xSortExpressionValue == null)
                {
                    xSortExpressionValue = GetDefaultValueOfPropertyType(propertyType);
                }

                object ySortExpressionValue = y.GetType().GetProperty(propertyName).GetValue(y, null);
                if (ySortExpressionValue == null)
                {
                    ySortExpressionValue = GetDefaultValueOfPropertyType(propertyType);
                }

                object result = compareToMethod.Invoke(xSortExpressionValue, new object[] { ySortExpressionValue });

                return sortReverser * _conversionHelper.ConvertStringToInteger(result.ToString());
            });
        }

        private MethodInfo GetCompareToMethod(Type propertyType)
        {
            return propertyType.GetMethod("CompareTo", new Type[] { propertyType });
        }

        private object GetDefaultValueOfPropertyType(Type propertyType)
        {
            if (propertyType == typeof(string))
            {
                return string.Empty;
            }
            else if (propertyType == typeof(int) || propertyType == typeof(decimal) || propertyType == typeof(float))
            {
                return -99999;
            }

            return null;
        }
    }
}